package com.king.designpatterns.行为模式.观察者模式;

/**
 * 观察者模式（Observer Pattern）也称发布订阅模式，它是一种在项目中经常使用的模式。
 *
 * 定义：定义对象间一种一对多的依赖关系，使得每当一个对象改变状态，则所有依赖于它的对象都会得到通知并被自动更新。
 *
 * 角色：
 *      ■ 抽象主题（Subject）角色：
 *          该角色又称为“被观察者”，可以增加和删除观察者对象。
 *      ■ 抽象观察者（Observer）角色：
 *          该角色为所有的具体观察者定义一个接口，在得到主题的通知时更新自己。
 *      ■ 具体主题（Concrete Subject）角色：
 *          该角色又称为“具体被观察者”，它将有关状态存入具体观察者对象，在具体主题的内部状态改变时，给所有登记过的观察者发出通知。
 *      ■ 具体观察者（Concrete Observer）角色：
 *          该角色实现抽象观察者所要求的更新接口，以便使自身的状态与主题的状态相协调。
 *
 * 优缺点：
 *      优点：
 *          ■ 观察者和被观察者之间是抽象耦合。被观察者角色所知道的只是一个具体观察者集合，每一个具体观察者都符合一个抽象观察者的接口。
 *              被观察者并不认识任何一个具体的观察者，它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密的耦合在一起，
 *              因此它们可以属于不同的抽象化层次，且都非常容易扩展。
 *          ■ 支持广播通信。被观察者会向所有登记过的观察者发出通知，这就是一个触发机制，形成一个触发链。
 *      缺点：
 *          ■ 如果一个主题有多个直接或间接的观察者，则通知所有的观察者会花费很多时间，且开发和调试都比较复杂。
 *          ■ 如果在主题之间有循环依赖，被观察者会触发它们之间进行循环调用，导致系统崩溃。在使用观察者模式时要特别注意这一点。
 *          ■ 如果对观察者的通知是通过另外的线程进行异步投递，系统必须保证投递的顺序执行。
 *          ■ 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化，但是观察者模式没有提供相应的机制使观察者知道所观察的对象是如何发生变化。
 *
 * 场景：
 *      ■ 关联行为场景。
 *      ■ 事件多级触发场景。
 *      ■ 跨系统的消息交换场景，如消息队列的处理机制。
 *
 * 注意事项：
 *      ■ 广播链的问题。
 *          一个观察者可以有双重身份，既是观察者也是被观察者，广播链一旦建立，逻辑就比较复杂，可维护性非常差。
 *          一般在一个观察者模式中最多出现一个对象既是观察者也是被观察者，这样消息最多转发一次（传递两次），较易控制。
 *      ■ 异步处理的问题。
 *          异步处理就要考虑线程安全和队列的问题。
 *
 * @author king
 * @date 2021-06-10 18:24
 */
public class ObserverPattern {
    public static void main(String[] args) {
        Button button = new Button();
        button.color = "白色";
        button.x = 0;
        button.y = 0;
        System.out.println(button);

        System.out.println("-------------------------------------");

        button.addClickableObserver(new ChangeColorObserver());
        button.addClickableObserver(new ChangeCoordinateObserver());
        button.addClickableObserver(new OtherObserver());
        button.click();
        System.out.println(button);
    }
}
